package fr.lip6.move.care.sdmaker.validation;

import java.util.ArrayList;

import org.eclipse.emf.common.util.EList;
import org.eclipse.xtext.common.types.JvmFormalParameter;
import org.eclipse.xtext.validation.Check;

import fr.lip6.move.care.sdmaker.sDMaker.Declaration;
import fr.lip6.move.care.sdmaker.sDMaker.Diagram;
import fr.lip6.move.care.sdmaker.sDMaker.SDMakerModel;
import fr.lip6.move.care.sdmaker.sDMaker.SDMakerPackage;
 

public class SDMakerJavaValidator extends AbstractSDMakerJavaValidator {
	/*
	 * - Chaque called d'un appel de méthode reférence le nom d'un Object
	 * - Les appel de méthodes se font sur des méthodes déclaré 
	 * - Bon bindings dans les references
	 * - Bon types pour les appels de méthodes
	 */

	@Check
	public void checkActorsNamesAreDifferents(Diagram d){
		ArrayList<String> actorsNames= SDMakerValidatorUtils.getAllActorsNames(d);

		for(int i= 0; i < actorsNames.size(); i++){
			for(int j= 0; j < actorsNames.size(); j++){
				if((i != j)){
					if(actorsNames.get(i).compareTo(actorsNames.get(j))==0){
						error("Actor named \""+actorsNames.get(i)+"\" should be uniq in diagram", SDMakerPackage.Literals.DIAGRAM__NAME);
						return;
					}
				}
			}
		}
	}

	@Check
	public void checkObjectsNamesAreDifferents(Diagram d){
		ArrayList<String> objectsNames= SDMakerValidatorUtils.getAllObjectsNames(d);

		for(int i= 0; i < objectsNames.size(); i++){
			for(int j= 0; j < objectsNames.size(); j++){
				if((i != j)){
					if(objectsNames.get(i).compareTo(objectsNames.get(j))==0){
						error("Object named \""+objectsNames.get(i)+"\" should be uniq in diagram", SDMakerPackage.Literals.DIAGRAM__NAME);
						return;
					}
				}
			}
		}
	}

	@Check
	public void checkNoConflitsNamesBetweenActorAndObject(Diagram d){
		ArrayList<String> actorsNames= SDMakerValidatorUtils.getAllActorsNames(d);
		ArrayList<String> objectsNames= SDMakerValidatorUtils.getAllObjectsNames(d);
		ArrayList<String> errors= new ArrayList<String>();

		for(int i= 0; i < actorsNames.size(); i++){
			for(int j= 0; j < objectsNames.size(); j++){
				if(actorsNames.get(i).compareTo(objectsNames.get(j))==0){
					errors.add("\""+objectsNames.get(i)+"\" is naming an Actor and an Object");
				}
			}
		}

		errors= SDMakerValidatorUtils.eraseMultipleSameString(errors);
		for(String error_mess : errors){
			error(error_mess, SDMakerPackage.Literals.DIAGRAM__NAME);
		}
	}

	@Check
	public void checkDiagramsNamesAreUniq(SDMakerModel model){
		EList<Diagram> diagrams= model.getDiagrams();
		for(int i= 0; i < diagrams.size(); i++){
			for(int j=0; j < diagrams.size(); j++){
				if(i!=j){
					if(diagrams.get(i).getName().compareTo(diagrams.get(j).getName())==0){
						error("Diagram named \""+diagrams.get(i).getName()+"\" should be uniq in model", null);
						return;
					}
				}
			}
		}
	}

	@Check
	public void checkDeclarationsAreUniq(SDMakerModel model){
		ArrayList<Declaration> allDeclaration= SDMakerValidatorUtils.getAllDeclarations(model);
		ArrayList<String>errors= new ArrayList<String>();

		
		/* *************************************************************
		 * Deux méthodes déclarés sont en conflits lorsqu'elles appartiennent 
		 * a la même interface, qu'elles ont le même nom et le même vecteur 
		 * de paramètres (aux noms des paramètre près). 
		 * *************************************************************/
		
		for(int i=0; i < allDeclaration.size(); i++){
			for(int j=0; j < allDeclaration.size(); j++){
				if(i != j){
					
					Declaration d1= allDeclaration.get(i);
					Declaration d2= allDeclaration.get(j);

					if(d1.getTypeOwner().compareTo(d1.getTypeOwner()) == 0){
						if(d1.getName().compareTo(d2.getName()) == 0){
							//on est dans le cas: meme interface et meme nom 
							
							EList<JvmFormalParameter> d1Params= d1.getParams();
							EList<JvmFormalParameter> d2Params= d2.getParams();
							Boolean findADiff= false;

							if(d1Params.size() == d2Params.size()){
								for(int k= 0; k < d1Params.size(); k++){
									
									String type1= d1Params.get(k)
											              .getParameterType()
											              .getSimpleName();
									String type2= d2Params.get(k)
											              .getParameterType()
											              .getSimpleName();
									
									if(type1.compareTo(type2) != 0){
										findADiff=true;
										break;
									}
								}

								if(findADiff == false){
									String d1STR= SDMakerValidatorUtils.declarationToString(d1);
									errors.add("\""+d1STR+"\" must be declared only once");
								}
							}
						}
					}
				}
			}
		}

		errors= SDMakerValidatorUtils.eraseMultipleSameString(errors);
		for(String error_mess: errors){
			error(error_mess, null);
		}
	}

	public void checkCallsAreCorrect(Diagram d){
		
	}

}